<template>
  <div id="app">
    <!-- 提示信息 -->
    <Header :counter="counter"/>
    <!-- 棋盘 -->
    <div class="chessboard">
      <div class="row" v-for="(i, index) in 3" :key="index">
        <Cell 
          class="cell" 
          v-for="(j, index) in 3" 
          :key="index" 
          :counter="counter"
          :i="i-1"
          :j="j-1"/>
      </div>
    </div>
    <!-- 操作 -->
    <Operation/>
    <!-- 历史记录 -->
    <history/>
  </div>
</template>

<script>
// 引入 Cell 组件
import Cell from '@/components/Cell.vue'
// 引入 Header 组件
import Header from '@/components/Header.vue'
// 引入 History 组件
import History from '@/components/History.vue'
// 引入 Operation 组件
import Operation from '@/components/Operation.vue'

export default {
  name: 'App',
  components: {
    Cell,
    Header,
    History,
    Operation
  },
  data() {
    return {
      // 棋盘信息
      chessboard: [['', '', ''], ['', '', ''], ['', '', '']],
      // 计数器：记录当前棋盘中共有几个落子
      counter: 0,
    }
  },
  mounted() {
    // 自定义事件：counter++ 和 同步棋盘状态。
    this.$bus.$on('chessValid', (i, j, val) => {
      this.counterAdd()
      this.cheSave(i, j, val)
    })

    // 自定义事件：重新开始，重置数据。
    this.$bus.$on('restart', () => this.reset())
  },
  beforeDestroy() {
    // 解绑自定义事件
    this.$bus.$off('chessValid')
    this.$bus.$off('restart')
  },
  methods: {
    /**
     *  将当前计数器 +1
     */
    counterAdd() {
      this.counter++
    },

    /**
     *  将当前落子的信息记录在棋盘 chessboard 中
     */
    cheSave(i, j, val) {
      // 将坐标和值添加到棋盘中
      this.chessboard[i][j] = val
      //判断是否有一方已经获胜
      if (this.checkWinner(i, j, val) !== null) {
        alert(`${val} 获得胜利`)
        // 触发 restart 事件
        this.$bus.$emit('restart')
        return
      }
      // 判断是否平局
      if (this.isBoardFull()) {
        alert("平局")
        // 触发 restart 事件
        this.$bus.$emit('restart')
      }
    },

    /**
     * 检查某一方是否已经获胜
     */
    checkWinner(row, col, val) {
      // 获取当前棋盘状态
      const board = this.chessboard
      // 标记是否有胜者
      let winner = null
      // 检查最后一步所在的行是否有相同的标记
      if (
        board[row][0] === val &&
        board[row][1] === val &&
        board[row][2] === val
      ) {
        winner = val
      }

      // 检查最后一步所在的列是否有相同的标记
      if (
        board[0][col] === val &&
        board[1][col] === val &&
        board[2][col] === val
      ) {
        winner = val
      }

      // 检查对角线是否有相同的标记（只需检查对角线如果最后一步在对角线上）
      if (row === col || row + col === 2) {
        // 如果最后一步在主对角线或副对角线上
        if (
          (board[0][0] === val && board[1][1] === val && board[2][2] === val) ||
          (board[0][2] === val && board[1][1] === val && board[2][0] === val)
        ) {
          winner = val
        }
      }

      return winner
    },

    /**
     * 检查是否平局
     * 也许可以使用算法提前预知，简单起见，这里只是判断棋盘是否已满。
     */
    isBoardFull() {
      // 检查数组中的每个位子是否已经有值
      return this.chessboard.every(row => row.every(cell => cell !== ''));
    },

    /**
     * 重置数据
     */
    reset() {
      // 重置棋盘信息和计数器
      this.chessboard = [['', '', ''], ['', '', ''], ['', '', '']],
      this.counter = 0
      // 触发 Cell 组件中的 reset 事件
      this.$bus.$emit('cellReset')
      // 触发 History 组件中的 reset 事件
      this.$bus.$emit('HistoryReset')
    }
  }
}
</script>

<style lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;

  font-size: 16px;

  // 棋盘
  .chessboard {
    margin: 0 auto;
    width: max-content;

    .row {
      display: flex;
      width: max-content;

      .cell {
        border-top: 1px solid black;
        border-left: 1px solid black;
      }

      .cell:last-child {
        border-right: 1px solid black;
      }
    }

    .row:last-child {
      .cell {
        border-bottom: 1px solid black;
      }
    }
  }
}
</style>
